home *** CD-ROM | disk | FTP | other *** search
/ Workbench Add-On / Workbench Add-On - Volume 1.iso / Music / MIDI / smusmidi / SMUSMIDI.C < prev    next >
C/C++ Source or Header  |  1995-08-23  |  46KB  |  1,232 lines

  1. /*
  2. ** SMUSMIDI.C Copyright © 1991 Thomas E. Janzen
  3. ** Converts a DMCS .SMUS file to a standard MIDI file.
  4. ** Don't expect it to work on SMUS files from programs other than DMCS.
  5. ** 7-7-91 resumed work on it.
  6. ** 25 July 91 works pretty well
  7. ** 27 July remove double math to avoid linking math lib.
  8. ** 15 Aug 91
  9. ** 17 August 1991 Works well enough for me. Version 1.0
  10. */
  11. /* Copyright (c) 1990 by Thomas E. Janzen
  12.    All Rights Reserved
  13.  
  14.    THIS SOFTWARE IS FURNISHED FREE OF CHARGE FOR STUDY AND USE AND MAY
  15.    BE COPIED ONLY FOR PERSONAL USE OR COMPLETELY AS OFFERED WITH NO
  16.    CHANGES FOR FREE DISTRIBUTION.  NO TITLE TO AND OWNERSHIP OF THE
  17.    SOFTWARE IS HEREBY TRANSFERRED.  THOMAS E. JANZEN ASSUMES NO 
  18.    RESPONSBILITY FOR THE USE OR RELIABILITY OF THIS SOFTWARE.
  19.    
  20.    THOMAS E. JANZEN ASSUMES NO RESPONSIBILITY FOR THE USE OF THIS
  21.    SOFTWARE TO COPY MUSICAL SCORE FILES PROTECTED BY COPYRIGHT LAWS.
  22.    THIS SOFTWARE IS FOR USE ONLY WITHIN ANY AND ALL APPLICABLE LAWS.
  23.  
  24.    Thomas E. Janzen
  25.    58A School St. Apt. 2-L
  26.    Hudson, MA 01749
  27.    (508)562-1295
  28. */
  29. /*
  30. **  FACILITY:
  31. **
  32. **    SMUSMIDI file format convertor on Commodore (TM) Amiga (TM)
  33. **    compiled with SAS/C (TM) 5.10a
  34. **
  35. **  ABSTRACT:
  36. **
  37. **  SMUSMIDI.c converts SMUS files from DMCS (TM Electronic Arts)
  38. **             into standard MIDI file format files. 
  39. **
  40. **  AUTHOR: Thomas E. Janzen
  41. **
  42. **  CREATION DATE:    17-AUG-1991
  43. **
  44. **  MODIFICATION HISTORY:
  45. **    DATE    NAME    DESCRIPTION
  46. **--
  47. */
  48. #include <stdlib.h>
  49. #include <stdio.h>
  50. #include <ctype.h>
  51. #include <string.h>
  52. #include <proto/exec.h>
  53. #include "iff/iff.h"
  54. #include "iff/smus.h"
  55.  
  56. #define MIDI_FILE_TYPE ".MID"
  57. #define IDLEN         4
  58. #define TRUE          1
  59. #define FALSE         0
  60. #define SINGLMULTTRAK 0
  61. #define MULTITRACK    1
  62. #define MIDIHDRLEN   14
  63. #define MIDITRKHDRLEN 8
  64. #define SYSEXLEN      4
  65. #define NTRK_POS    12
  66. #define TICKS_PER_QUARTER 240
  67. #define NOTEON       0X90
  68. #define NOTEOFF      0X80
  69. #define META_EVENT   0XFF
  70. #define SEQ_NUM      0X00
  71.  
  72. #define TEXT_EVENT   0X01
  73. #define COPY_EVENT   0X02
  74. #define TRACK_NAME   0X03
  75. #define INST_NAME    0X04
  76. #define LYRIC_EVENT  0X05
  77. #define MARKER_EVENT 0X06
  78. #define CUE_POINT    0X07
  79. #define CHAN_PREFIX  0X20
  80. #define EOT_EVENT    0X2F
  81. #define TEMPO_EVENT  0X51
  82. #define TIME_SIG_EVENT 0X58
  83. #define KEY_EVENT    0X59
  84. #define MAX_TIES     32
  85. #define MAX_CHORDS   32
  86. #define NOT_OLD_CHORD 0x40000000
  87.  
  88. struct MIDI_Note_struct {
  89.    unsigned char  Status_Channel,
  90.                   Note_Number,
  91.                   Velocity;
  92. };
  93. typedef struct MIDI_Note_struct MIDI_NOTE_TYPE;
  94.  
  95. struct MIDI_Header {
  96.    unsigned int Chunk_Type;
  97.    unsigned int Chunk_Len;
  98.    unsigned short int Format;
  99.    unsigned short int Num_Tracks;
  100.    unsigned short int Division; /* of time, usu. 24 MIDI ticks or SMPTE */
  101. };
  102. typedef struct MIDI_Header MIDI_HEADER_TYPE;
  103.  
  104. struct MIDI_Track {
  105.    unsigned int Chunk_Type;
  106.    unsigned int Chunk_Len;
  107. };
  108. typedef struct MIDI_Track MIDI_TRACK_TYPE;
  109.  
  110. struct Chord_Struct {
  111.    unsigned char  Pitch, 
  112.                   Tied,
  113.                   Tied_Back,
  114.                   Delete;
  115. };
  116. typedef struct Chord_Struct CHORD_TYPE;
  117.  
  118. static char *MIDItoPitchName (int NoteNum, char *PitchName);
  119. static int SMUS_Len_to_MIDI_Delay (SEvent *Note);
  120. static int Variable_Length_Values (int Number, unsigned char *Array);
  121. static int Search_Tied_Array (char Pitch, char *Tied_Array, 
  122.                               int Tied_Index);
  123. static int Remove_Tied_Note (int Pitch, char *Tied_Array, int Tied_Index);
  124. static void Insert_Null (unsigned int *MIDI_Index, 
  125.                                  unsigned char *MIDI_Score);
  126. static void Insert_Meta_Event (unsigned int *MIDI_Index,
  127.                                        unsigned char *MIDI_Score,
  128.                                        unsigned char Event_Type,
  129.                                        unsigned int Event_Len);
  130. static void Send_a_Note (  unsigned int *MIDI_Index,
  131.                            unsigned char *MIDI_Score,
  132.                            unsigned char Current_Channel,
  133.                            unsigned char Current_Dynamic,
  134.                            unsigned char Pitch,
  135.                            unsigned char *Running_Status);
  136. static void Shutdown (void);
  137. static int Remove_Chord_Notes ( CHORD_TYPE *Chord_Array, 
  138.                                int Chord_Array_Len);
  139. static int Check_Tie (char *SMUS_Score, int SMUS_Index, SEvent Note, 
  140.                      int FORM_Size);
  141. static int Search_Chord_Array (  char Pitch, 
  142.                                  CHORD_TYPE *Chord_Array, 
  143.                                  int Chord_Index,
  144.                                  int Tied);
  145. static int Add_Chord_Array (CHORD_TYPE *Chord_Array, unsigned char Pitch,
  146.                               int Tie, int Tie_Back, int Chord_Index);
  147.  
  148. static unsigned char *SMUS_Score = NULL,
  149.                      *MIDI_Score = NULL;
  150. static FILE *SMUS_File = NULL,
  151.             *MIDI_File = NULL;
  152. static unsigned int Just_Did_a_Delay = FALSE;
  153.  
  154. void main (int argc, char *argv[])
  155. {
  156.    static unsigned char 
  157.                Track_String[32],
  158.                Current_Channel,
  159.                Current_Dynamic = 127,
  160.                Tied_Array[MAX_TIES],
  161.                key;
  162.    static CHORD_TYPE Chord_Array[MAX_CHORDS];
  163.    static MIDI_HEADER_TYPE MIDI_FileHdr = 
  164.                            {MakeID('M','T','h','d'), 6, 
  165.                               MULTITRACK, 1, TICKS_PER_QUARTER};
  166.    auto MIDI_TRACK_TYPE  *MIDI_Track_ptr;
  167.    auto unsigned char Score_Name[128],
  168.                       Running_Status = 0;
  169.    static char SMUS_File_Name[128] = "Score.smus",
  170.                MIDI_File_Name[128] = "ram:Score",
  171.                filemode[2] = "r";
  172.    static SScoreHeader Header;
  173.    auto unsigned int FORM_Size = 0,
  174.                      Instrument_Index,
  175.                      Track,
  176.                      Temp_ID,
  177.                      MIDI_Track_Index,
  178.                      status,
  179.                      tempint,
  180.                      ID_int,
  181.                      MIDI_Delay = 0,
  182.                      len,
  183.                      Real_Tie;
  184. #ifdef DEBUG
  185.    auto int          debug_stopper = 62;                     
  186. #endif
  187.    auto int          Chord_Index = 0,
  188.                      Chord_Counter = 0,
  189.                      Tied_Index = 0,
  190.                      Notes_per_Track,
  191.                      Chord_Note;
  192.    static unsigned int  Start_of_Tracks_Index,
  193.                         SMUS_Index = 0,
  194.                         MIDI_Index = 0,
  195.                         Caesura = TICKS_PER_QUARTER / 24;
  196.    static RefInstrument Instruments[32];
  197.    static SEvent Note;
  198.    static int Note_Counter;
  199.    union {
  200.       unsigned int Tempo_int;
  201.       unsigned char Tempo_char[4];
  202.    } MIDI_Tempo;
  203.  
  204.    if (argc != 3) 
  205.    {
  206.        printf ("usage: SMUSMIDI {SMUS_file} {MIDI_file(no type)}\n");
  207.        exit (1);
  208.    }
  209.    strcpy (SMUS_File_Name, argv[1]);
  210.    if  ((SMUS_File = fopen (SMUS_File_Name, filemode)) == NULL) 
  211.    {
  212.         printf ("Can't open SMUS input file.\n");
  213.         exit (1);
  214.    }
  215.    strcpy (filemode, "w");
  216.    strcpy (MIDI_File_Name, argv[2]);
  217.    strcat (MIDI_File_Name, MIDI_FILE_TYPE);
  218.    if  ((MIDI_File = fopen (MIDI_File_Name, filemode)) == NULL) 
  219.    {
  220.          printf ("Can't open MIDI output file.\n");
  221.          Shutdown ();
  222.    }
  223.    status = fread ((char *)&ID_int, sizeof (int), 1, SMUS_File);
  224.    if (ID_int != FORM)
  225.    {
  226.       printf ("Not a FORM file\n");
  227.       Shutdown ();
  228.    }
  229.    status = fread ((char *)&FORM_Size, sizeof (int), 1, SMUS_File);
  230.    printf ("FORM is: %d bytes.\n", FORM_Size);
  231.  
  232.    SMUS_Score = malloc (FORM_Size);
  233.    if (SMUS_Score == NULL)
  234.    {
  235.       printf ("Insufficient memory for SMUS Score\n");
  236.       Shutdown ();
  237.       exit (0);
  238.    }
  239.    MIDI_Score = malloc (4 * FORM_Size);
  240.    memset (MIDI_Score, '\0', 4 * FORM_Size);
  241.    if (MIDI_Score == NULL)
  242.    {
  243.       printf ("Insufficient memory for MIDI Score\n");
  244.       Shutdown ();
  245.    }
  246.    /* Copy whole file into RAM */
  247.    fread (SMUS_Score, FORM_Size, 1, SMUS_File);
  248.    fclose (SMUS_File);
  249.    SMUS_File = NULL;
  250.    
  251.    /* check for SMUS */
  252.    SMUS_Index = 0;
  253.    memcpy ((char *)&ID_int, &SMUS_Score[SMUS_Index], 4);
  254.    if (ID_int != ID_SMUS)
  255.    {
  256.       printf ("Input file was not an SMUS file!?\n");
  257.       Shutdown ();
  258.    }
  259.    SMUS_Index += 4;
  260.    /* check for SHDR */
  261.    memcpy ((char *)&ID_int, &SMUS_Score[SMUS_Index], 4);
  262.    if (ID_int != ID_SHDR)
  263.    {
  264.       printf ("No SHDR chunk!\n");
  265.       Shutdown ();
  266.    }
  267.    /* Get the header */   
  268.    SMUS_Index += 8;
  269.    memcpy ((char *)&Header, &SMUS_Score[SMUS_Index], 
  270.             sizeof (SScoreHeader));
  271.    MIDI_FileHdr.Num_Tracks = Header.ctTrack + 1; 
  272.          /* hope it's < 256 tracks! + tempo track */
  273.    printf ("HEADER:\n  Tempo: MM %d; %d Tracks\n",
  274.             Header.tempo / 128, Header.ctTrack);
  275.    SMUS_Index += sizeof (SScoreHeader);
  276.       
  277.    /* Start MIDI_Score */
  278.    MIDI_Index = 0;
  279.    memcpy (&MIDI_Score[MIDI_Index], &MIDI_FileHdr, 
  280.          sizeof (MIDI_HEADER_TYPE));
  281.    MIDI_Index += sizeof (MIDI_HEADER_TYPE);
  282.    /* Check for NAME */
  283.    memcpy ((char *)&ID_int, &SMUS_Score[SMUS_Index], sizeof (int));
  284.    if (ID_int != ID_NAME)
  285.    {
  286.       printf ("ID Name didn't show up.\n");
  287.       Shutdown ();
  288.    }
  289.    /* Get NAME */
  290.    SMUS_Index += IDLEN;
  291.    memcpy ((char *)&tempint, &SMUS_Score[SMUS_Index], sizeof (int));
  292.    SMUS_Index += sizeof (int);
  293.    memcpy ((char *)Score_Name, &SMUS_Score[SMUS_Index], tempint);
  294.    Score_Name[tempint] = '\0';
  295.    printf ("SCORE: %s\n", Score_Name);
  296.    SMUS_Index += tempint + (tempint % 2);
  297.    
  298.    /* Check for INS1 */
  299.    do
  300.    {
  301.       memcpy ((char *)&ID_int, &SMUS_Score[SMUS_Index], sizeof (int));
  302.       if (ID_int != ID_INS1)
  303.       {
  304.          printf ("No more instruments.\n");
  305.          break;
  306.       }
  307.       SMUS_Index += IDLEN;
  308.       /* copy NAME */
  309.       memcpy ((char *)&tempint, &SMUS_Score[SMUS_Index], sizeof (int));
  310.       SMUS_Index += sizeof (int);
  311.       Instrument_Index = 0;
  312.       memcpy ( &Instruments[Instrument_Index],
  313.                &SMUS_Score[SMUS_Index], tempint);
  314.       Instruments[Instrument_Index].name[tempint - 4] = '\0';
  315.             /* terminate name */
  316.       printf ("  Instrument: %s\n", 
  317.                Instruments[Instrument_Index].name);
  318.       SMUS_Index += tempint + (tempint % 2);
  319.       if (Instruments[Instrument_Index].type == INS1_MIDI)
  320.       {
  321.          printf ("MIDI instrument, channel %d, preset %d\n",
  322.                   Instruments[Instrument_Index].data1,
  323.                   Instruments[Instrument_Index].data2);
  324.       }
  325.    } while (status = TRUE);
  326.    /* Instrument index is the number of instruments now.*/
  327.    /* I hope all the instruments have been listed by now.*/
  328.    /* 
  329.    ** DO THE TEMPO TRACK 
  330.    */
  331.    Start_of_Tracks_Index = SMUS_Index;
  332.    MIDI_Track_ptr = (MIDI_TRACK_TYPE *)(&(MIDI_Score[MIDI_Index]));
  333.    MIDI_Track_Index = MIDI_Index;
  334.    Temp_ID = MakeID ('M', 'T', 'r', 'k');
  335.    memcpy ((char *)&MIDI_Track_ptr->Chunk_Type, (char *)&Temp_ID,
  336.       sizeof (int));
  337.    MIDI_Index += sizeof (MIDI_TRACK_TYPE);
  338.    memcpy ((char *)&ID_int, &SMUS_Score[SMUS_Index], sizeof (int));
  339.    SMUS_Index += sizeof (int);
  340.    memcpy ((char *)&tempint, &SMUS_Score[SMUS_Index], sizeof (int));
  341.    SMUS_Index += sizeof (int);
  342.    printf ("Length of track: %d bytes\n", tempint);
  343.    Notes_per_Track = tempint / sizeof (SEvent);
  344.  
  345.    MIDI_Score[MIDI_Index] = 0;   /* must have a delay before an Event */
  346.    MIDI_Index++;
  347.    MIDI_Score[MIDI_Index] = META_EVENT;
  348.    MIDI_Index++;
  349.    MIDI_Score[MIDI_Index] = TRACK_NAME;
  350.    MIDI_Index++;
  351.    len = Variable_Length_Values (5, &MIDI_Score[MIDI_Index]);
  352.    MIDI_Index += len;
  353.    strcpy (&MIDI_Score[MIDI_Index], "Tempo");
  354.    MIDI_Index += 5;
  355.  
  356.    Just_Did_a_Delay = FALSE;
  357.    MIDI_Delay = 0;
  358.    for (Note_Counter = 0; Note_Counter < Notes_per_Track;
  359.          Note_Counter++)
  360.    {
  361.       memcpy (&Note, &SMUS_Score[SMUS_Index], sizeof (SEvent));
  362.       SMUS_Index += sizeof (SEvent);
  363.       switch (Note.sID)
  364.       {
  365.          case SID_Rest:
  366.             do {
  367.                MIDI_Delay += SMUS_Len_to_MIDI_Delay (&Note);
  368.                memcpy (&Note, &SMUS_Score[SMUS_Index], sizeof (SEvent));
  369.                SMUS_Index += sizeof (SEvent);
  370.                Note_Counter++;
  371.             } while ((Note.sID == SID_Rest) 
  372.                      && (Note_Counter < Notes_per_Track));
  373.             Note_Counter--;
  374.             SMUS_Index -= sizeof (SEvent);
  375.             Just_Did_a_Delay = TRUE;
  376.            break;
  377.          case SID_Instrument:
  378.             break;
  379.          case SID_TimeSig:
  380.             MIDI_Index  = MIDI_Index 
  381.                         + Variable_Length_Values 
  382.                         (MIDI_Delay, &MIDI_Score[MIDI_Index]);
  383.             MIDI_Delay  = 0;
  384.             Just_Did_a_Delay = TRUE;
  385.             Insert_Meta_Event (&MIDI_Index, MIDI_Score, TIME_SIG_EVENT, 4);
  386.             MIDI_Score[MIDI_Index] = TimeNSig (Note.data) + 1;
  387.             MIDI_Index++;
  388.             MIDI_Score[MIDI_Index] = TimeDSig (Note.data);
  389.             MIDI_Index++;
  390.             MIDI_Score[MIDI_Index] = 24;
  391.             MIDI_Index++;
  392.             MIDI_Score[MIDI_Index] = 0x08;
  393.             MIDI_Index++;
  394.             Just_Did_a_Delay = FALSE;
  395.             break;
  396.          case SID_KeySig:
  397.          case SID_Dynamic:
  398.          case SID_MIDI_Chnl:
  399.          case SID_MIDI_Preset:
  400.          case SID_Clef:
  401.             break;
  402.          case SID_Tempo:
  403.             MIDI_Index   = MIDI_Index 
  404.                          + Variable_Length_Values 
  405.                 (MIDI_Delay, &MIDI_Score[MIDI_Index]);
  406.             MIDI_Delay = 0;
  407.             Just_Did_a_Delay = TRUE;
  408.             Insert_Meta_Event (&MIDI_Index, MIDI_Score, TEMPO_EVENT, 3);
  409.             MIDI_Tempo.Tempo_int = (60 * 1000000) / Note.data;
  410.             memcpy (&MIDI_Score[MIDI_Index], 
  411.                    &(MIDI_Tempo.Tempo_char[1]), 3);
  412.             MIDI_Index += 3;
  413.             break;
  414.          case SID_Mark:
  415.             break;
  416.          default:
  417.             if ((SID_FirstNote <= Note.sID) && (Note.sID <= SID_LastNote))
  418.             {
  419.                if (!IsChord (Note.data)) /* if the note is chorded */
  420.                {
  421.                   MIDI_Delay += SMUS_Len_to_MIDI_Delay (&Note);
  422.                }
  423.             } 
  424.       }
  425.    }
  426.    MIDI_Index   = MIDI_Index 
  427.                 + Variable_Length_Values 
  428.        (MIDI_Delay, &MIDI_Score[MIDI_Index]);
  429.    MIDI_Delay = 0;
  430.    Just_Did_a_Delay = TRUE;
  431.    Insert_Meta_Event (&MIDI_Index, MIDI_Score, EOT_EVENT, 0);
  432.    Temp_ID = MIDI_Index - MIDI_Track_Index - 8; 
  433.    memcpy ((char *)&MIDI_Track_ptr->Chunk_Len, (char *)&Temp_ID,
  434.       sizeof (int));
  435.    Running_Status = 0;
  436.    /* 
  437.    ** end of tempo track 
  438.    */
  439.    SMUS_Index = Start_of_Tracks_Index;
  440.    for (Track = 0; Track < Header.ctTrack; Track++)
  441.    {
  442.       MIDI_Track_ptr = (MIDI_TRACK_TYPE *)(&(MIDI_Score[MIDI_Index]));
  443.       MIDI_Track_Index = MIDI_Index;
  444.       Temp_ID = MakeID ('M', 'T', 'r', 'k');
  445.       memcpy ((char *)&MIDI_Track_ptr->Chunk_Type, (char *)&Temp_ID,
  446.          sizeof (int));
  447.       MIDI_Index += sizeof (MIDI_TRACK_TYPE);
  448.       /* Make sure you put in the chunk length at the end! */      
  449.       memcpy ((char *)&ID_int, &SMUS_Score[SMUS_Index], sizeof (int));
  450.       if (ID_int != ID_TRAK)
  451.       {
  452.          printf ("There are no Tracks!\n");
  453.       }
  454.       SMUS_Index += sizeof (int);
  455.       memcpy ((char *)&tempint, &SMUS_Score[SMUS_Index], sizeof (int));
  456.       SMUS_Index += sizeof (int);
  457.       MIDI_Score[MIDI_Index] = 0;   /* must have a delay before an Event */
  458.       MIDI_Index++;
  459.       MIDI_Score[MIDI_Index] = META_EVENT;
  460.       MIDI_Index++;
  461.       MIDI_Score[MIDI_Index] = TRACK_NAME;
  462.       MIDI_Index++;
  463.       sprintf (Track_String, "Track %d", Track);
  464.       len = Variable_Length_Values (strlen (Track_String), 
  465.                                     &MIDI_Score[MIDI_Index]);
  466.       MIDI_Index += len;
  467.       strcpy (&MIDI_Score[MIDI_Index], Track_String);
  468.       MIDI_Index += strlen (Track_String);
  469.       Notes_per_Track = tempint / sizeof (SEvent);
  470.       Just_Did_a_Delay = FALSE;
  471.       for (Note_Counter = 0; Note_Counter < Notes_per_Track;
  472.             Note_Counter++)
  473.       {
  474.          memcpy (&Note, &SMUS_Score[SMUS_Index], sizeof (SEvent));
  475.          SMUS_Index += sizeof (SEvent);
  476.          switch (Note.sID)
  477.          {
  478.             case SID_Rest:
  479.                MIDI_Delay = 0;
  480.                do 
  481.                {
  482.                   MIDI_Delay += SMUS_Len_to_MIDI_Delay (&Note);
  483.                   memcpy (&Note, &SMUS_Score[SMUS_Index], sizeof (SEvent));
  484.                   SMUS_Index += sizeof (SEvent);
  485.                   Note_Counter++;
  486.                } while ((Note.sID == SID_Rest) 
  487.                         && (Note_Counter < Notes_per_Track));
  488.                Note_Counter--;
  489.                SMUS_Index -= sizeof (SEvent);
  490.                if (Just_Did_a_Delay) /* 2 delays can't appear together */
  491.                {
  492.                   Insert_Null (&MIDI_Index, MIDI_Score);
  493.                }
  494.                MIDI_Index  = MIDI_Index 
  495.                            + Variable_Length_Values 
  496.                            (MIDI_Delay, &MIDI_Score[MIDI_Index]);
  497.                Just_Did_a_Delay = TRUE;
  498.               break;
  499.             case SID_Instrument:
  500.             case SID_TimeSig:
  501.                break;
  502.             case SID_KeySig:
  503.                switch (Note.data)
  504.                {
  505.                   case 0: case 1: case 2: case 3: case 4: case 5:
  506.                   case 6: case 7:
  507.                      key = Note.data & 0x7F;
  508.                      break;
  509.                   case 8: case 9: case 10: case 11:
  510.                   case 12: case 13: case 14:
  511.                      key = ((7 - Note.data) & 0x7F);
  512.                      break;
  513.                   default:
  514.                      break;
  515.                }
  516.                Insert_Meta_Event (&MIDI_Index, MIDI_Score, KEY_EVENT, 2);
  517.                MIDI_Score[MIDI_Index] = key;
  518.                MIDI_Index++;
  519.                MIDI_Score[MIDI_Index] = 0x00;
  520.                MIDI_Index++;
  521.                break;
  522.             case SID_Dynamic:
  523.                Current_Dynamic = Note.data;
  524.                break;
  525.             case SID_MIDI_Chnl:
  526.                Current_Channel = Note.data;
  527.                Insert_Meta_Event (&MIDI_Index, MIDI_Score, CHAN_PREFIX, 1);
  528.                MIDI_Score[MIDI_Index] = Note.data;
  529.                MIDI_Index++;
  530.                break;
  531.             case SID_MIDI_Preset:
  532.                if (!Just_Did_a_Delay)
  533.                {
  534.                   MIDI_Score[MIDI_Index] = 0;
  535.                   MIDI_Index++;
  536.                }
  537.                MIDI_Score[MIDI_Index] = 0xC0 | Current_Channel;
  538.                MIDI_Index++;
  539.                MIDI_Score[MIDI_Index] = Note.data;
  540.                MIDI_Index++;
  541.                Running_Status = 0xC0 | Current_Channel;
  542.                break;
  543.             case SID_Clef:
  544.             case SID_Tempo:
  545.             case SID_Mark:
  546.                break;
  547.             default:
  548.                if ((SID_FirstNote <= Note.sID) /* if it's a pitch number */
  549.                   && (Note.sID <= SID_LastNote))
  550.                {
  551.                   Real_Tie = Check_Tie (SMUS_Score, SMUS_Index,
  552.                                         Note, FORM_Size);
  553.                   /*
  554.                   ** The following tedious logic decides 
  555.                   **   whether to send a note
  556.                   **   whether to delay
  557.                   **   whether to stop the note
  558.                   ** on the basis of
  559.                   **   whether the note is in the tied array
  560.                   **   whether the note is in the chord array
  561.                   **   whether the note is chorded forward
  562.                   **   whether the note is tied forward
  563.                   */
  564. #ifdef DEBUG
  565.                   if (Note.sID == debug_stopper)
  566.                   {
  567.                       puts ("stopit");
  568.                   }
  569. #endif
  570.                   if (Real_Tie) /* if the note is tied forward */
  571.                   {
  572.                      if (Search_Tied_Array (Note.sID, Tied_Array, 
  573.                          Tied_Index)) /* and if the note is tied backward*/
  574.                      {
  575.                         if (IsChord (Note.data)) /* and if it's Chorded */
  576.                         {
  577.                            if (Search_Chord_Array (Note.sID, Chord_Array, 
  578.                               Chord_Index, Real_Tie) != NOT_OLD_CHORD) 
  579.                               /* and if it's not in an old chord */
  580.                            {
  581.                               ;
  582.                            }
  583.                            else
  584.                            {
  585.                               Chord_Index = Add_Chord_Array (Chord_Array, 
  586.                               Note.sID, Real_Tie, TRUE, Chord_Index);
  587.                            }
  588.                         }
  589.                         else /* tied forward and backward,but not chorded*/
  590.                         /* this means that we are at the end of a chord
  591.                         ** and should play off the non-tied notes in chord 
  592.                         */
  593.                         {
  594.                            if (Search_Chord_Array (Note.sID, Chord_Array, 
  595.                               Chord_Index, Real_Tie) != NOT_OLD_CHORD)
  596.                            /* tied forward/backward;old chord, not chord */
  597.                            {
  598.                               if (Just_Did_a_Delay)
  599.                               {
  600.                                  Insert_Null (&MIDI_Index, MIDI_Score);
  601.                               }
  602.                               MIDI_Delay  = SMUS_Len_to_MIDI_Delay (&Note)
  603.                                           - Caesura;
  604.                               MIDI_Index  = MIDI_Index 
  605.                                           + Variable_Length_Values 
  606.                                     (MIDI_Delay, &MIDI_Score[MIDI_Index]);
  607.                               Just_Did_a_Delay = TRUE;
  608.                               /* send note off for chord notes */
  609.                               for ( Chord_Counter = 0;
  610.                                  Chord_Counter < Chord_Index; 
  611.                                  Chord_Counter++)
  612.                               {
  613.                                  if (!Chord_Array[Chord_Counter].Tied)
  614.                                  {
  615.                                     Send_a_Note (&MIDI_Index, MIDI_Score, 
  616.                                     Current_Channel, 0, 
  617.                                     Chord_Array[Chord_Counter].Pitch, 
  618.                                     &Running_Status);
  619.                                     Chord_Array[Chord_Counter].Delete 
  620.                                           = TRUE;
  621.                                     Tied_Index = 
  622.                                     Remove_Tied_Note (
  623.                                     Chord_Array[Chord_Counter].Pitch, 
  624.                                     Tied_Array, Tied_Index);
  625.                                  }
  626.                               }
  627.                               if (Just_Did_a_Delay)
  628.                               {
  629.                                  Insert_Null (&MIDI_Index, MIDI_Score);
  630.                               }
  631.                               MIDI_Score[MIDI_Index] = Caesura;
  632.                               MIDI_Index++;
  633.                               Just_Did_a_Delay = TRUE;
  634.                            }
  635.                            else  /* tied forward/backward, but
  636.                                  ** not in an old chord and not chorded */
  637.                            {
  638.                               if (Just_Did_a_Delay)
  639.                               {
  640.                                  Insert_Null (&MIDI_Index, MIDI_Score);
  641.                               }
  642.                               MIDI_Delay  = SMUS_Len_to_MIDI_Delay (&Note)
  643.                                           - Caesura;
  644.                               MIDI_Index  = MIDI_Index 
  645.                                     + Variable_Length_Values 
  646.                                     (MIDI_Delay, &MIDI_Score[MIDI_Index]);
  647.                               Just_Did_a_Delay = TRUE;
  648.                               /* send note off for non-tied chord notes */
  649.                               for ( Chord_Counter = 0;
  650.                                  Chord_Counter < Chord_Index; 
  651.                                  Chord_Counter++)
  652.                               {
  653.                                  if (!Chord_Array[Chord_Counter].Tied)
  654.                                  {
  655.                                     Send_a_Note (&MIDI_Index, MIDI_Score, 
  656.                                     Current_Channel, 0, 
  657.                                     Chord_Array[Chord_Counter].Pitch, 
  658.                                     &Running_Status);
  659.                                     Chord_Array[Chord_Counter].Delete 
  660.                                        = TRUE;
  661.                                     Tied_Index = 
  662.                                     Remove_Tied_Note (
  663.                                     Chord_Array[Chord_Counter].Pitch, 
  664.                                     Tied_Array, Tied_Index);
  665.                                  }
  666.                               }
  667.                               if (Just_Did_a_Delay)
  668.                               {
  669.                                  Insert_Null (&MIDI_Index, MIDI_Score);
  670.                               }
  671.                               MIDI_Score[MIDI_Index] = Caesura;
  672.                               MIDI_Index++;
  673.                               Just_Did_a_Delay = TRUE;
  674.                            }
  675.                         }
  676.                      }
  677.                      else /* tied forward but not backward */
  678.                      { 
  679.                         /* add to Tied_Array */
  680.                         Tied_Array[Tied_Index] = Note.sID;
  681.                         Tied_Index++;
  682.                         if (IsChord (Note.data)) /*if the note is chorded*/
  683.                         {
  684.                            if ((Chord_Note = 
  685.                               Search_Chord_Array (Note.sID, Chord_Array, 
  686.                               Chord_Index, Real_Tie)) == NOT_OLD_CHORD)
  687.                            /* if not in chord array */
  688.                            {
  689.                               Chord_Index = Add_Chord_Array (Chord_Array, 
  690.                               Note.sID, Real_Tie, FALSE, Chord_Index);
  691.                               Send_a_Note (&MIDI_Index, MIDI_Score, 
  692.                                  Current_Channel, Current_Dynamic, 
  693.                                  Note.sID, &Running_Status);
  694.                            }
  695.                            else
  696.                            {
  697.                               if (!Chord_Array[Chord_Note].Tied_Back)
  698.                               {
  699.                                  Send_a_Note (&MIDI_Index, MIDI_Score, 
  700.                                  Current_Channel, Current_Dynamic, 
  701.                                  Note.sID, &Running_Status);
  702.                               }
  703.                            }
  704.                         }
  705.                         else /* tied forward, not tied back, not chord */
  706.                         /* we are at the end of a chord, so we have to play
  707.                         ** all the non-tied chord notes */
  708.                         {
  709.                            Chord_Note = 
  710.                               Search_Chord_Array (Note.sID, Chord_Array, 
  711.                               Chord_Index, Real_Tie);
  712.                            if (Chord_Note != NOT_OLD_CHORD)
  713.                            {
  714.                               if (!Chord_Array[Chord_Note].Tied_Back)
  715.                               {
  716.                                  Send_a_Note (&MIDI_Index, MIDI_Score, 
  717.                                     Current_Channel, Current_Dynamic, 
  718.                                     Note.sID, &Running_Status);
  719.                               }
  720.                            }
  721.                            else
  722.                            {
  723.                               Send_a_Note (&MIDI_Index, MIDI_Score, 
  724.                                  Current_Channel, Current_Dynamic, 
  725.                                  Note.sID, &Running_Status);
  726.                            } 
  727.                            if (Just_Did_a_Delay)
  728.                            {
  729.                               Insert_Null (&MIDI_Index, MIDI_Score);
  730.                            }
  731.                            MIDI_Delay  = SMUS_Len_to_MIDI_Delay (&Note) 
  732.                                        - Caesura;
  733.                            MIDI_Index  = MIDI_Index 
  734.                                     + Variable_Length_Values 
  735.                                     (MIDI_Delay, &MIDI_Score[MIDI_Index]);
  736.                            Just_Did_a_Delay = TRUE;
  737.                            /* send note off for non-tied chord notes */
  738.                            for ( Chord_Counter = 0;
  739.                                  Chord_Counter < Chord_Index; 
  740.                                  Chord_Counter++)
  741.                            {
  742.                               if (!Chord_Array[Chord_Counter].Tied)
  743.                               {
  744.                                  Send_a_Note (&MIDI_Index, MIDI_Score, 
  745.                                  Current_Channel, 0, 
  746.                                  Chord_Array[Chord_Counter].Pitch, 
  747.                                  &Running_Status);
  748.                                  Chord_Array[Chord_Counter].Delete = TRUE;
  749.                                  Tied_Index = 
  750.                                     Remove_Tied_Note (
  751.                                     Chord_Array[Chord_Counter].Pitch, 
  752.                                     Tied_Array, Tied_Index);
  753.                               }
  754.                            }
  755.                            if (Just_Did_a_Delay)
  756.                            {
  757.                               Insert_Null (&MIDI_Index, MIDI_Score);
  758.                            }
  759.                            MIDI_Score[MIDI_Index] = Caesura;
  760.                            MIDI_Index++;
  761.                            Just_Did_a_Delay = TRUE;
  762.                         } 
  763.                      } 
  764.                   } 
  765.                   else /* it's not tied to the next note */
  766.                   {
  767.                      /* if the note is in the tied array */
  768.                      if (Search_Tied_Array (Note.sID, Tied_Array, 
  769.                          Tied_Index))
  770.                      {
  771.                         Tied_Index = 
  772.                         Remove_Tied_Note (Note.sID, Tied_Array, 
  773.                                           Tied_Index);
  774.                         if (IsChord (Note.data)) /* if chorded */
  775.                         {
  776.                            if (Search_Chord_Array (Note.sID, Chord_Array, 
  777.                                Chord_Index, Real_Tie) == NOT_OLD_CHORD)
  778.                            /* if not in chord array */
  779.                            {
  780.                               Chord_Index = Add_Chord_Array (Chord_Array, 
  781.                               Note.sID, Real_Tie, TRUE, Chord_Index);
  782.                            }
  783.                         }
  784.                         else /* tied backward not forward, not a chord */ 
  785.                         {
  786.                            if (Just_Did_a_Delay) 
  787.                            {
  788.                               Insert_Null (&MIDI_Index, MIDI_Score);
  789.                            }
  790.                            MIDI_Delay = SMUS_Len_to_MIDI_Delay (&Note) 
  791.                                        - Caesura;
  792.                            /* 
  793.                            ** Caesura is for time to get in the note off 
  794.                            ** so the synth doesn't choke
  795.                            */
  796.                            MIDI_Index = MIDI_Index + Variable_Length_Values
  797.                               (MIDI_Delay, &MIDI_Score[MIDI_Index]);
  798.                            Just_Did_a_Delay = TRUE;
  799.                            if (Search_Chord_Array (Note.sID, Chord_Array, 
  800.                                Chord_Index, Real_Tie) == NOT_OLD_CHORD)
  801.                            {
  802.                               Send_a_Note (&MIDI_Index, MIDI_Score, 
  803.                                  Current_Channel, 0, 
  804.                                  Note.sID, &Running_Status);
  805.                            }
  806.                            /* send note off for all chord notes */
  807.                            for ( Chord_Counter = 0;
  808.                                  Chord_Counter < Chord_Index; 
  809.                                  Chord_Counter++)
  810.                            {
  811.                               if (!Chord_Array[Chord_Counter].Tied)
  812.                               {
  813.                                  Send_a_Note (&MIDI_Index, MIDI_Score, 
  814.                                     Current_Channel, 0, 
  815.                                     Chord_Array[Chord_Counter].Pitch, 
  816.                                     &Running_Status);
  817.                                     Tied_Index = 
  818.                                     Remove_Tied_Note (
  819.                                     Chord_Array[Chord_Counter].Pitch, 
  820.                                     Tied_Array, Tied_Index);
  821.                                  Chord_Array[Chord_Counter].Delete = TRUE;
  822.                               }
  823.                            }
  824.                            if (Just_Did_a_Delay) 
  825.                            {
  826.                               Insert_Null (&MIDI_Index, MIDI_Score);
  827.                            }
  828.                            MIDI_Score[MIDI_Index] = Caesura;
  829.                            MIDI_Index++;
  830.                            Just_Did_a_Delay = TRUE;
  831.                         } 
  832.                      }
  833.                      else /* not tied backwards or forwards */ 
  834.                      {
  835.                         if (IsChord (Note.data)) /* if chorded */
  836.                         {
  837.                            if (( Chord_Note = Search_Chord_Array 
  838.                                  (Note.sID, Chord_Array, Chord_Index, 
  839.                                  Real_Tie)) == NOT_OLD_CHORD)
  840.                            {
  841.                               Chord_Index = Add_Chord_Array (Chord_Array, 
  842.                               Note.sID, Real_Tie, FALSE, Chord_Index);
  843.                               Send_a_Note (&MIDI_Index, MIDI_Score, 
  844.                                  Current_Channel, Current_Dynamic, 
  845.                                  Note.sID, &Running_Status);
  846.                                  /*this was not sending the extra notes*/
  847.                            }
  848.                            else
  849.                            {
  850.                               if (!Chord_Array[Chord_Note].Tied_Back)
  851.                               {
  852.                                  Send_a_Note (&MIDI_Index, MIDI_Score, 
  853.                                  Current_Channel, Current_Dynamic, 
  854.                                  Note.sID, &Running_Status);
  855.                               }
  856.                            }
  857.                         }
  858.                         else /* not tied back or forward, not chorded */
  859.                         {
  860.                            Chord_Note = 
  861.                               Search_Chord_Array (Note.sID, Chord_Array, 
  862.                               Chord_Index, Real_Tie);
  863.                            if (Chord_Note != NOT_OLD_CHORD)
  864.                            {
  865.                               if (!Chord_Array[Chord_Note].Tied_Back)
  866.                               {
  867.                                  Send_a_Note (&MIDI_Index, MIDI_Score, 
  868.                                     Current_Channel, Current_Dynamic, 
  869.                                     Note.sID, &Running_Status);
  870.                               }
  871.                            } 
  872.                            else
  873.                            {
  874.                               Send_a_Note (&MIDI_Index, MIDI_Score, 
  875.                                  Current_Channel, Current_Dynamic, 
  876.                                  Note.sID, &Running_Status);
  877.                            }
  878.                            if (Just_Did_a_Delay)
  879.                            {
  880.                               Insert_Null (&MIDI_Index, MIDI_Score);
  881.                            }
  882.                            MIDI_Delay = SMUS_Len_to_MIDI_Delay (&Note) 
  883.                                        - Caesura;
  884.                            MIDI_Index  = MIDI_Index 
  885.                                        + Variable_Length_Values 
  886.                                        (MIDI_Delay, 
  887.                                        &MIDI_Score[MIDI_Index]);
  888.                            Just_Did_a_Delay = TRUE;
  889.                            if (Chord_Note == NOT_OLD_CHORD) 
  890.                            {
  891.                               Send_a_Note (&MIDI_Index, MIDI_Score, 
  892.                                  Current_Channel, 0, 
  893.                                  Note.sID, &Running_Status);
  894.                            }
  895.                            /* send note off for all chord notes */
  896.                            for ( Chord_Counter = 0; 
  897.                                  Chord_Counter < Chord_Index; 
  898.                                  Chord_Counter++)
  899.                            {
  900.                               if (!Chord_Array[Chord_Counter].Tied)
  901.                               {
  902.                                  Send_a_Note (&MIDI_Index, MIDI_Score, 
  903.                                     Current_Channel, 0, 
  904.                                     Chord_Array[Chord_Counter].Pitch, 
  905.                                     &Running_Status);
  906.                                     Tied_Index = 
  907.                                     Remove_Tied_Note (
  908.                                     Chord_Array[Chord_Counter].Pitch, 
  909.                                     Tied_Array, Tied_Index);
  910.                                     Chord_Array[Chord_Counter].Delete 
  911.                                        = TRUE;
  912.                               }
  913.                            }
  914.                            if (Just_Did_a_Delay) 
  915.                            {
  916.                               Insert_Null (&MIDI_Index, MIDI_Score);
  917.                            }
  918.                            MIDI_Score[MIDI_Index] = Caesura;
  919.                            MIDI_Index++;
  920.                            Just_Did_a_Delay = TRUE;
  921.                         }   
  922.                      } 
  923.                   }
  924.                }
  925.                Chord_Index = Remove_Chord_Notes (Chord_Array, Chord_Index);
  926.                break;
  927.          }
  928.       }
  929.       Insert_Meta_Event (&MIDI_Index, MIDI_Score, EOT_EVENT, 0);
  930.       Temp_ID = MIDI_Index - MIDI_Track_Index - 8; 
  931.       memcpy ((char *)&MIDI_Track_ptr->Chunk_Len, (char *)&Temp_ID,
  932.          sizeof (int));
  933.       Running_Status = 0;
  934.       Chord_Index = 0;
  935.       Tied_Index = 0;
  936.    }
  937.    fwrite (MIDI_Score, MIDI_Index, 1, MIDI_File);
  938.    fflush (MIDI_File); 
  939.    Shutdown ();
  940.    exit (0);
  941. }
  942.  
  943. static int SMUS_Len_to_MIDI_Delay (SEvent *Note)
  944. {
  945.    auto long int Length;
  946.    
  947.    Length = (4 * TICKS_PER_QUARTER) << 15; /* one scaled unit is 0x8000 */
  948.    if (IsDot (Note->data))
  949.    {
  950.       Length *= 3;
  951.    }
  952.  
  953.    switch (NTuplet (Note->data))
  954.    {
  955.       case 1:  /* triplet */
  956.          Length *= 2;
  957.          Length /= 3;
  958.          break;
  959.       case 2:  /* quintuplet */
  960.          Length *= 4;
  961.          Length /= 5;
  962.          break;
  963.       case 3:  /* septuplet */
  964.          Length *= 6;
  965.          Length /= 7;
  966.          break;
  967.       default:
  968.          break;
  969.    }
  970.    if (IsDot (Note->data))
  971.    {
  972.       Length /= 2;
  973.    }
  974.    
  975.    Length = Length >> Division (Note->data);
  976.    Length += 0x4000; /* add a half unit to round off by truncating. */
  977.    Length = Length >> 15;
  978.    return Length;
  979. }
  980.  
  981. static int Variable_Length_Values (int Number, unsigned char *Array)
  982. {
  983.    auto unsigned char   Byte4,
  984.                         MSByte, 
  985.                         MIDbyte, 
  986.                         LSByte;
  987.                
  988.    LSByte = (Number & 0x0000007F);
  989.    MIDbyte = ((Number & 0x00003F80) >> 7) | 0x80;
  990.    MSByte = ((Number & 0x001FC000) >> 14) | 0x80;
  991.    Byte4 = ((Number &  0x0FE00000) >> 21) | 0x80;
  992.    if (Byte4 != 0x80)
  993.    {
  994.       Array[0] = Byte4;
  995.       Array[1] = MSByte;
  996.       Array[2] = MIDbyte;
  997.       Array[3] = LSByte;
  998.       return 4;
  999.    }
  1000.    if (MSByte != 0x80)
  1001.    {
  1002.       Array[0] = MSByte;
  1003.       Array[1] = MIDbyte;
  1004.       Array[2] = LSByte;
  1005.       return 3;
  1006.    }
  1007.  
  1008.    if (MIDbyte != 0x80)
  1009.    {
  1010.       Array[0] = MIDbyte;
  1011.       Array[1] = LSByte;
  1012.       return 2;
  1013.    }
  1014.    Array[0] = LSByte;
  1015.   
  1016.    return 1;
  1017. }
  1018.  
  1019. static int Search_Tied_Array (   char Pitch, 
  1020.                                  char *Tied_Array, 
  1021.                                  int Tied_Index)
  1022. {
  1023.    auto int Tied_Counter;
  1024.    
  1025.    for (Tied_Counter = 0; Tied_Counter < Tied_Index; Tied_Counter++)
  1026.    {
  1027.       if (Pitch == Tied_Array[Tied_Counter])
  1028.       {
  1029.          return TRUE;
  1030.       }
  1031.    }
  1032.    return FALSE;
  1033. }
  1034.  
  1035. static int Search_Chord_Array (  char Pitch, 
  1036.                                  CHORD_TYPE *Chord_Array, 
  1037.                                  int Chord_Index,
  1038.                                  int Tied)
  1039. {
  1040.    auto int Chord_Counter;
  1041.    
  1042.    for (Chord_Counter = 0; Chord_Counter < Chord_Index; Chord_Counter++)
  1043.    {
  1044.       if (Pitch == Chord_Array[Chord_Counter].Pitch)
  1045.       {
  1046.          if (Chord_Array[Chord_Counter].Tied)
  1047.          {
  1048.             Chord_Array[Chord_Counter].Tied_Back = TRUE;
  1049.          }
  1050.          Chord_Array[Chord_Counter].Tied = Tied;
  1051.          return Chord_Counter;
  1052.       }
  1053.    }
  1054.    return NOT_OLD_CHORD;
  1055. }
  1056.  
  1057. static int Remove_Tied_Note (int Pitch, char *Tied_Array, int Tied_Index)
  1058. {
  1059.    auto int Tied_Counter,
  1060.             Inner_Index;
  1061.  
  1062.    for (Tied_Counter = 0; Tied_Counter < Tied_Index; Tied_Counter++)
  1063.    {
  1064.       if (Tied_Array[Tied_Counter] == Pitch)
  1065.       {
  1066.          for ( Inner_Index = Tied_Counter; Inner_Index < Tied_Index;
  1067.                Inner_Index++)
  1068.          {
  1069.             Tied_Array[Inner_Index] = Tied_Array[Inner_Index + 1];
  1070.          }
  1071.          Tied_Index--;
  1072.          break;
  1073.       }
  1074.    }
  1075.    return Tied_Index;
  1076. }
  1077.  
  1078. static int Remove_Chord_Notes ( CHORD_TYPE *Chord_Array, 
  1079.                                int Chord_Array_Len)
  1080. {
  1081.    auto CHORD_TYPE New_Chord_Array[MAX_CHORDS];
  1082.    auto int Chord_Index = 0,
  1083.             New_Chord_Counter = 0;
  1084.  
  1085.    for (Chord_Index = 0; Chord_Index < Chord_Array_Len; Chord_Index++)
  1086.    {
  1087.       if (!Chord_Array[Chord_Index].Delete)
  1088.       {
  1089.           New_Chord_Array[New_Chord_Counter] = Chord_Array[Chord_Index];
  1090.           New_Chord_Counter++;
  1091.       }
  1092.    }
  1093.    for (Chord_Index = 0; Chord_Index < New_Chord_Counter; Chord_Index++)
  1094.    {
  1095.       Chord_Array[Chord_Index] =New_Chord_Array[Chord_Index];
  1096.    }
  1097.    return New_Chord_Counter;
  1098. }
  1099.  
  1100. static void Insert_Null (unsigned int *MIDI_Index, 
  1101.                          unsigned char *MIDI_Score)
  1102. {
  1103.    Insert_Meta_Event (MIDI_Index, MIDI_Score, TEXT_EVENT, 4);
  1104.    strcpy (&MIDI_Score[*MIDI_Index], "NULL");
  1105.    (*MIDI_Index) += 4;
  1106.    return;
  1107. }
  1108.  
  1109. static void Insert_Meta_Event (unsigned int *MIDI_Index,
  1110.                                unsigned char *MIDI_Score,
  1111.                                unsigned char Event_Type,
  1112.                                unsigned int Event_Len)
  1113. {
  1114.    if (!Just_Did_a_Delay)
  1115.    {
  1116.        MIDI_Score[*MIDI_Index] = 0x00;
  1117.        (*MIDI_Index)++;
  1118.    }
  1119.    MIDI_Score[*MIDI_Index] = META_EVENT;
  1120.    (*MIDI_Index)++;
  1121.    MIDI_Score[*MIDI_Index] = Event_Type;
  1122.    (*MIDI_Index)++;
  1123.    MIDI_Score[*MIDI_Index] = Event_Len;
  1124.    (*MIDI_Index)++;
  1125.    Just_Did_a_Delay = FALSE;
  1126.    return;
  1127. }
  1128.  
  1129. static void Send_a_Note (  unsigned int *MIDI_Index,
  1130.                            unsigned char *MIDI_Score,
  1131.                            unsigned char Current_Channel,
  1132.                            unsigned char Current_Dynamic,
  1133.                            unsigned char Pitch,
  1134.                            unsigned char *Running_Status)
  1135. {
  1136.    static MIDI_NOTE_TYPE MIDI_Note;
  1137.  
  1138.    if (!Just_Did_a_Delay)
  1139.    {
  1140.        MIDI_Score[*MIDI_Index] = 0x00;
  1141.        (*MIDI_Index)++;
  1142.    }
  1143.    MIDI_Note.Status_Channel = NOTEON | Current_Channel;
  1144.    MIDI_Note.Note_Number = Pitch;
  1145.    MIDI_Note.Velocity = Current_Dynamic;
  1146.    if (MIDI_Note.Status_Channel == *Running_Status)
  1147.    {
  1148.       memcpy ( &MIDI_Score[*MIDI_Index], &(MIDI_Note.Note_Number), 2);
  1149.       (*MIDI_Index) += 2;
  1150.    }
  1151.    else  /* running status changed */
  1152.    {
  1153.       memcpy (&MIDI_Score[*MIDI_Index], &MIDI_Note, sizeof MIDI_Note);
  1154.       (*MIDI_Index) += sizeof (MIDI_NOTE_TYPE);
  1155.       *Running_Status = MIDI_Note.Status_Channel;
  1156.    }
  1157.    Just_Did_a_Delay = FALSE;
  1158.    return;
  1159. }
  1160.  
  1161. static void Shutdown (void)
  1162. {
  1163.    if (SMUS_Score) free (SMUS_Score); 
  1164.    if (MIDI_Score) free (MIDI_Score);
  1165.    if (SMUS_File)  fclose (SMUS_File);
  1166.    if (MIDI_File)  fclose (MIDI_File);
  1167.    exit (0);
  1168. }
  1169.  
  1170. static int Check_Tie (char *SMUS_Score, int SMUS_Index, SEvent Note, 
  1171.                      int FORM_Size)
  1172. {
  1173.    auto SEvent Note_temp;
  1174.  
  1175.    /* Pass the end of the current chord to look into the next chord */
  1176.    if (IsChord (Note.data))
  1177.    {
  1178.       do
  1179.       {
  1180.          memcpy (&Note_temp, &SMUS_Score[SMUS_Index], sizeof (SEvent));
  1181.          SMUS_Index += sizeof (SEvent); /* point to next event */
  1182.       } while ((SMUS_Index < FORM_Size) && (IsChord (Note_temp.data)));
  1183.    }
  1184.    /* Now pointing to beginning of next chord or note */
  1185.    if (!IsTied (Note.data)) /* if it's not tied, it's not tied */
  1186.    {
  1187.       return FALSE;
  1188.    }
  1189.    /* if it was tied, check that there is a next same pitch to tie to */
  1190.    while (SMUS_Index < FORM_Size)
  1191.    {
  1192.       memcpy (&Note_temp, &SMUS_Score[SMUS_Index], sizeof (SEvent));
  1193.       SMUS_Index += sizeof (SEvent);
  1194.       if ((  SID_FirstNote <= Note_temp.sID) /* if it's a note event */
  1195.          && (Note_temp.sID <= SID_LastNote))
  1196.       {
  1197.          if (!IsChord (Note_temp.data)) /* if at end of next chord */
  1198.          {
  1199.             if (Note.sID == Note_temp.sID)/*last chance to match tie note*/
  1200.             {
  1201.                return TRUE;
  1202.             }
  1203.             return FALSE; /* the last note in next chord didn't match */
  1204.          }
  1205.          else /* we're in a note inside the next chord */
  1206.          {
  1207.             if (Note_temp.sID == Note.sID) /* if it matches the tie */
  1208.             {
  1209.                return TRUE; /* return true */
  1210.             }
  1211.          }  /* otherwise keep looking through this chord */
  1212.       }
  1213.    }
  1214.    return FALSE;
  1215. }
  1216.  
  1217. static int Add_Chord_Array (CHORD_TYPE *Chord_Array, unsigned char Pitch,
  1218.                               int Tie, int Tie_Back, int Chord_Index)
  1219. {
  1220.    if (Chord_Index == (MAX_CHORDS - 1))
  1221.    {
  1222.       puts ("chord array too long");
  1223.       Shutdown();
  1224.    }
  1225.    Chord_Array[Chord_Index].Pitch     = Pitch;
  1226.    Chord_Array[Chord_Index].Tied      = Tie;
  1227.    Chord_Array[Chord_Index].Tied_Back = Tie_Back;
  1228.    Chord_Array[Chord_Index].Delete    = FALSE;
  1229.    Chord_Index++;
  1230.    return Chord_Index;
  1231. }
  1232.